package org.pushforward.iwillsurvive.data;

import java.sql.SQLException;
import java.util.Iterator;
import java.util.LinkedHashSet;

import org.pushforward.iwillsurvive.data.TypeValuePair.PairTypeEnum;
import org.pushforward.iwillsurvive.helpers.Utils;

/**
 * @author  Sabre Runner
 */
public class User
{
	static final DatabaseManager db = DatabaseManager.getInstance(); 

	private String email = null;
	private String password = null;
	private String name = null;
	private String photoSrc = null;
	private LinkedHashSet<Post>	posts = new LinkedHashSet<Post>();

	private void LoadUserFromDB() throws SQLException
	{
		String[] popUserStatement = {"select * from users where email=?;"};
		TypeValuePair[][] popUserPair = {{new TypeValuePair(PairTypeEnum.STRING, email)}};
		StringBuilder resultSet = new StringBuilder();

		boolean success = db.ExecuteStatements(popUserStatement, popUserPair, resultSet);
		if (!success || resultSet.length() == 0)
		{
			throw new SQLException("User grab failure.");
		}

		String resultString = resultSet.toString().replaceAll("\\n", "");
		String[] userData = resultString.split(",");

		setEmail(userData[0]);
		setPassword(userData[1]);
		setName(userData[2]);
		setPhotoSrc(userData[3]);

		String[] getPostsStatement = {"select * from posts where email=?;"};
		resultSet.setLength(0);

		success = db.ExecuteStatements(getPostsStatement, popUserPair, resultSet);

		if (success)
		{
			String[] posts = resultSet.toString().split("\\n");
			this.posts.clear();

			for (String postString : posts)
			{
				try
				{
					Post tempPost = new Post(postString.split(","), false);
					this.posts.add(tempPost);
				}
				catch (SQLException e)
				{
					System.err.println("Something that shouldn't have happened, happened.");
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * Creates a user instance given a user's email
	 * @param email the user's email
	 * @param loadFromDB set whether to load the given user from database
	 * @throws SQLException
	 */
	public User(String email, boolean loadFromDB) throws SQLException
	{
		this.email = email;

		if (loadFromDB)
		{
			Utils.Log("Loading user: " + email);
			LoadUserFromDB();
		}
	}

	public boolean SaveUserToDB()
	{
		Utils.Log("Saving user: " + this.email);
		String[] saveUserStatment = {"update users set password=?, name=?, photosrc=? where email=?;"};
		TypeValuePair[][] saveUserPairs= {{new TypeValuePair(PairTypeEnum.STRING, this.Password()),
			new TypeValuePair(PairTypeEnum.STRING, this.Name()),
			new TypeValuePair(PairTypeEnum.STRING, this.PhotoSrc()),
			new TypeValuePair(PairTypeEnum.STRING, this.Email())}};

		return db.ExecuteStatements(saveUserStatment, saveUserPairs);
	}

	public String Email()
	{
		return this.email;
	}
	public void setEmail(String email)
	{
		this.email = email;
	}
	public String Password()
	{
		return this.password;
	}
	public void setPassword(String password)
	{
		this.password = password;
	}
	public String Name()
	{
		return this.name;
	}
	public void setName(String name)
	{
		this.name = name;
	}
	public String PhotoSrc()
	{
		return this.photoSrc;
	}
	public void setPhotoSrc(String photoSrc)
	{
		this.photoSrc = photoSrc;
	}
	public String Posts()
	{
		if (this.posts.isEmpty())
		{
			return "";
		}
		
		StringBuilder postsBuilder = new StringBuilder();
		Iterator<Post> iter = this.posts.iterator();

		while (iter.hasNext())
		{
			Post post = iter.next();
			postsBuilder.append(post.toString());
		}

		postsBuilder.setLength(postsBuilder.length() - 1);
		return postsBuilder.toString();
	}
	public boolean AddPost(String[] postFields)
	{
		try
		{
			Post tempPost = new Post(postFields, true);
			this.posts.add(tempPost);
		} 
		catch (SQLException e)
		{
			System.err.println(e.getMessage());
			e.printStackTrace();
			return false;
		}
		return true;
	}
	public boolean RemovePost(Integer id)
	{
		try
		{
			Post tempPost = new Post(id.intValue());
			if (!this.posts.contains(tempPost))
			{
				return false;
			}
			this.posts.remove(tempPost);
		} catch (SQLException e)
		{
			System.err.println(e.getMessage());
			e.printStackTrace();
			return false;
		}

		String[] removePostStatement = {"delete from posts where id=?;"};
		TypeValuePair[][] removePostParameters = {{new TypeValuePair(PairTypeEnum.INT, id)}};

		return db.ExecuteStatements(removePostStatement, removePostParameters);
	}

	public boolean Delete()
	{
		Utils.Log("Deleting user: " + this.email);
		String[] deleteUserStatement = {"delete from users where email=?;"};
		String[] deleteRoleStatement = {"delete from roles where email=?;"};
		String[] updatePostsStatement = {"update posts set users = replace(users, ?, '');"};
		TypeValuePair[][] deleteUserPair = {{new TypeValuePair(PairTypeEnum.STRING, this.email)}};
		TypeValuePair[][] updatePostsPair = {{new TypeValuePair(PairTypeEnum.STRING, "@" + this.email)}};
		
		if (!db.ExecuteStatements(deleteUserStatement, deleteUserPair))
		{
			return false;
		}
		
		if (!db.ExecuteStatements(deleteRoleStatement, deleteUserPair))
		{
			return false;
		}

		Iterator<Post> iter = posts.iterator();
		while (iter.hasNext())
		{
			Post post = iter.next();
			RemovePost(new Integer(post.Id()));
		}
		
		db.ExecuteStatements(updatePostsStatement, updatePostsPair);
		
		return true;
	}
	
	@Override
	public int hashCode()
	{
		return this.email.hashCode();
	}
}
